home *** CD-ROM | disk | FTP | other *** search
- /* ***** BEGIN LICENSE BLOCK *****
-
- This code has been relicensed under LGPL as permitted by original license.
-
- Copyright Cumulate Draw Editor
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- * ***** END LICENSE BLOCK ***** */
-
- /**
- *RichDrawEditor: the idea is to provide an abstract editor interface which
- *manipulates vml or svg renderers,
- *
- *constructor, set up initial values for state variables and add listeners
- **/
-
-
- function RichDrawEditor(elem, renderer) {
- gApplication = new Application();
- this.initialized=false;
- this.iUser='';
- this.container = elem;
- this.page=$("_page");
- this.width=700;
- this.height=700;
- this.DEFAULT_PAGE_WIDTH=700;
- this.DEFAULT_PAGE_HEIGHT=700;
- this.MAX_WIDTH=2000;
- this.MAX_HEIGHT=2000;
- this.gridX = 1;
- this.gridY = 1;
- this.mouseDownX = 0;
- this.mouseDownY = 0;
- this.prevZoom=1.0;
- this.zoom=1.0;
- this.prevWidth=0;
- this.prevHeight=0;
- this.prevLeft=0;
- this.prevTop=0;
- this.prevRotation=0;
- this.prevMode='';
- this.mode = 'select';
- this.resizeMode='';//possible values are left-stretch, right-stretch,top-stretch,bottom-stretch
- this.fillColor = '';
- this.lineColor = '';
- this.lineWidth = '';
- this.lineStyle='none';
- this.opacity='1.0';
- this.gradient='solid';
- this.linedashstyle='solid';
- this.shadowOn="false";
- this.shiftMode=false;
- this.selected = null;
- //the current shape which is under line draw!!!
- this.lineActiveShape=null;
- this.dragStarted=false;
- this.textEditMode=false;
- this.textToolBeginNew=true;
- this.resizeCounter=0;
- this.dragCounter=0;
- var font=new Object();
- font.size='';
- font.family='';
- font.color='';
- font.align='';
- font.italics='';
- font.bold='';
- this.fillUpFont(font);
- this.font=font;
- this.shapeProps=new Array();
- this.shapeProps["table"]=$("_shapeTable");
- this.shapeProps["x"]=$("_x");
- this.shapeProps["y"]=$("_y");
- this.shapeProps["width"]=$("_width");
- this.shapeProps["height"]=$("_height");
- this.shapeProps["rotation"]=$("_rotation");
- this.lineProps=new Array();
- this.lineProps["table"]=$("_connectorTable");
- this.lineProps["x1"]=$("_x1");
- this.lineProps["x2"]=$("_x2");
- this.lineProps["y1"]=$("_y1");
- this.lineProps["y2"]=$("_y2");
- this.lineProps["type"]=$("_lineType");
- this.pageProps=new Array();
- this.pageProps["table"]=$("_pageTable");
- this.pageProps["x"]=$("_pageX");
- this.pageProps["y"]=$("_pageY");
- this.pageProps["width"]=$("_pageWidth");
- this.pageProps["height"]=$("_pageHeight");
- //one day we will allow multiple objects in the clipboard
- this.clipboard=null;
- this.selectedBounds = { x:0, y:0, width:0, height: 0 };
-
- this.onselect = function() {}
- this.onunselect = function() {}
- //initialize the renderer
- this.renderer = renderer;
- this.renderer.init(this.container);
-
- this.onMouseDownListener = this.onMouseDown.bindAsEventListener(this);
- this.onMouseUpListener = this.onMouseUp.bindAsEventListener(this);
- this.onDragListener = this.onDrag.bindAsEventListener(this);
- this.onDrawListener = this.onDraw.bindAsEventListener(this);
-
- this.onHitListener = this.onHit.bindAsEventListener(this);
-
-
- this.onSelectStartListener = this.onSelectStart.bindAsEventListener(this);
- this.onMouseOverListener=this.onMouseOver.bindAsEventListener(this);
- this.onMouseOutListener=this.onMouseOut.bindAsEventListener(this);
- this.onShapeMouseOutListener=this.onShapeMouseOut.bindAsEventListener(this);
- this.onShapeMouseEnterListener=this.onShapeMouseEnter.bindAsEventListener(this);
- this.onKeyPressListener=this.onKeyPress.bindAsEventListener(this);
- this.onKeyUpListener=this.onKeyUp.bindAsEventListener(this);
- this.onDblClickListener=this.onDblClick.bindAsEventListener(this);
- this.onTextEditEndListener=this.onTextEditEnd.bindAsEventListener(this);
- Event.observe(this.container, "mousedown", this.onMouseDownListener);
- Event.observe(this.container, "mouseup", this.onMouseUpListener);
- Event.observe(this.container,"mouseout",this.onMouseOutListener);
- Event.observe(this.container, "selectstart", this.onSelectStartListener);
- Event.observe(this.container.ownerDocument,'keypress',this.onKeyPressListener);
- Event.observe(this.container.ownerDocument,'keyup',this.onKeyUpListener);
- }
-
- /**
- *setup initial values for the font
- **/
- RichDrawEditor.prototype.fillUpFont=function(font){
- if(font.size=='')
- font.size=16;
- if(font.family=='')
- font.family="'arial'";
- if(font.italics=='')
- font.italics="normal";
- if(font.bold=='')
- font.bold="normal"
- if(font.align=='')
- font.align="center";
- if(font.color=='')
- font.color="black";
-
-
- }
-
- /**
- *Initialized the workspace
- **/
- RichDrawEditor.prototype.initializationDone = function() {
- this.initialized=true;
- };
-
-
- /**
- *clear the workspace
- **/
- RichDrawEditor.prototype.clearWorkspace = function() {
- this.container.innerHTML = '';
-
- };
- /******************************begin cut/copy/paste/delete operations***********************************/
- /**
- *delete the selection and remove the trackers
- **/
- RichDrawEditor.prototype.deleteSelection = function() {
-
- if (this.selected) {
- //remove all tracker components!!
- if($('tracker-group')){
-
- Event.stopObserving($('tracker-group'),"mouseover",this.onMouseOverListener);
- }
- Event.stopObserving(this.selected,"dblclick",this.onDblClickListener);
- this.renderer.remove(this.container.ownerDocument.getElementById('tracker-group'));
- this.renderer.remove(this.selected);
- this.selected = null;
- //this.updateShapeInfo(null);
- }
- else{
- setHelp("Select a shape to delete");
- }
- };
-
- /**
- *copy and then delete the selection
- **/
- RichDrawEditor.prototype.cut=function(){
- if(this.selected){
- this.copy();
- this.deleteSelection();
- this.unselect();
- }
- else{
- setHelp("Nothing to cut,Please select a shape first");
- }
- };
-
- /**
- *Save to the clipboard
- */
-
- RichDrawEditor.prototype.copyToRemote=function(){
- if(this.selected){
- return this.renderer.copy(this.selected);
- }
- return null;
- };
-
- RichDrawEditor.prototype.copy=function(){
- if(this.selected){
- //I know this is weird but clone node does not seem to work,so we copy the outer html
- this.clipboard=this.renderer.copy(this.selected);
- }
- else{
- setHelp("Nothing to copy,Please select a shape first");
- }
- };
-
- /**
- *paste function
- *wierd IE bug which forces us to set zindex of lines to 0 until they are added
- *nodeArray[i].getElementsByTagName("line")[0].style.zIndex=0;
- *another wierdness is that polyline.points.value does not correspond to polyline.points.item(x).value, so we
- * first set the points to 0,0, then add them to the container and then set the orignal points which we preserved
- * during copy, where we called savePolyLinePath
- **/
- RichDrawEditor.prototype.paste=function(){
-
- if(this.clipboard!=null){
- var node=this.renderer.paste(this.clipboard);
- //add listener to added child
- this.addNewShapeListeners(node);
- this.clipboard=this.renderer.copy(node);
- return node;
- }
- else{
- setHelp("Nothing to paste,Use copy or cut on selected shape");
- }
-
- }
-
- /**
- * a utility function to add all the required listener after a new shape has been
- * added
- **/
- RichDrawEditor.prototype.addNewShapeListeners=function(shape){
- if(!shape)return;
- Event.observe(shape, "mousedown", this.onHitListener);
-
- Event.observe(shape,"mouseover",this.onShapeMouseEnterListener);
- Event.observe(shape,"mouseout",this.onShapeMouseOutListener);
- }
-
-
- /****END DELETE, CUT,COPY,PASTE functions*****************/
- /****************BRING TO FRONT/BACK FUNCTIONS*************************/
- /**
- *bring to front,the listeners are refreshed since in SVG there is no real z-index operation, so
- *we remove and readd!
- *@param shape
- **/
- RichDrawEditor.prototype.bringToFront=function(shape){
- var subject=(shape)?shape:this.selected;
- subject=this.renderer.bringToFront(subject);
- if(subject){
- this.addNewShapeListeners(subject);
- this.select(subject);
- }
- }
- /**
- *send to back, the listeners are refreshed since in SVG there is no real z-index operation, so
- *we remove and readd!.
- *@param shape
- **/
- RichDrawEditor.prototype.sendToBack=function(shape){
-
- var subject=(shape)?shape:this.selected;
- var subject=this.renderer.sendToBack(subject);
- if(subject){
- this.addNewShapeListeners(subject);
- this.select(subject);
- }
- }
- /*********************END BRING TO FRONT/BACK FUNCTIONS**********************/
-
- /**
- * select and show tracker
- **/
- RichDrawEditor.prototype.select = function(elem) {
- if (elem == this.selected)
- return;
-
- this.selected = elem;
- var tracker=this.renderer.showTracker(this.selected);
- Event.observe(tracker,"mouseover",this.onMouseOverListener);
- // if(!this.renderer.isConnector(this.selected)){
- Event.observe(this.selected,"dblclick",this.onDblClickListener);
- //}
- setHelp("To move the shape, drag it. To resize, use resize boxes.<b>To Set Text, double click</b>");
- this.onselect(this);
- this.updateShapeInfo(this.selected);
- };
-
- /**
- *unselect and remove tracker,
- *if text is being edited, end that operation.
- **/
- RichDrawEditor.prototype.unselect = function() {
-
- if (this.selected!=null) {
- if(this.textEditMode){
- this.finishTextEdit();
- this.textEditMode=false;
- }
- if(this.mode!="text"){
- this.textModeBeginNew=false;
- }
- Event.stopObserving(this.selected,"dblclick",this.onDblClickListener);
- this.selected = null;
- this.onunselect(this);
- Event.stopObserving(this.container,"mouseover",this.onMouseOverListener);
-
- this.updateShapeInfo(null);
- if(this.container.ownerDocument.getElementById('tracker-group')!=null){
- this.renderer.remove(this.container.ownerDocument.getElementById('tracker-group'));
-
-
- }
-
- var activeShapeTracker=$("active-shape-tracker");
- if(activeShapeTracker)
- this.renderer.remove(activeShapeTracker);
- }
- var lineTracker=$("line-tracker");
- if(lineTracker){
- this.renderer.remove(lineTracker);
- }
- }
- /***************************************TEXT related functions************************/
- /**
- *this is called when a shape is double clicked,
- *it displays the text box for the selected shape
- **/
- RichDrawEditor.prototype.onDblClick=function(event){
- if(!this.selected){
- return false;
- }
-
- else{
- this.startTextEdit(this.selected);
- }
- }
-
- /**
- *start the text editing
- *@param {shape} the shape
- **/
- RichDrawEditor.prototype.startTextEdit=function(shape){
-
- setHelp("Enter your text and then click anywhere outside the text area");
- var text=$('__shapeText');
- var textString=this.renderer.getShapeText(shape);
- if(textString){
- text.value=textString;
- }
- else{
- text.value="";
- }
- text.style.visibility="visible";
- var bounds=this.renderer.getTextBounds(shape,"",this.zoom);
- text.style.marginLeft=bounds.x>3?(bounds.x-3):0;
- text.style.marginTop=bounds.y>3?(bounds.y-3):0;
- if(bounds.width>=35){
- text.style.width=parseInt(bounds.width)+6;
- }
- else{
- text.style.width=35;
- }
- if(bounds.height>=35){
- text.style.height=parseInt(bounds.height)+6;
- }
- else{
- text.style.height=35;
- }
-
- this.setTextAreaFont(text);
-
- this.renderer.remove(text);
- this.container.appendChild(text);
- text.focus();
- text.style.zIndex=this.renderer.maxIndex;
- Event.stopObserving(this.container, "mousedown", this.onMouseDownListener);
- Event.stopObserving(this.container, "mouseup", this.onMouseUpListener);
- Event.stopObserving(this.container, "selectstart", this.onSelectStartListener);
- Event.stopObserving(this.container,'keypress',this.onKeyPressListener);
- Event.stopObserving(this.container,'keyup',this.onKeyUpListener);
- Event.stopObserving(this.container, "mousemove", this.onDragListener);
- Event.observe(this.container,'mousedown',this.onTextEditEndListener);
- setTimeout("c.manageTextSize()",100);
- this.textEditMode=true;
- }
- /**
- * manage the size of the text area based on size of the text being entered
- */
- RichDrawEditor.prototype.manageTextSize=function(){
- if(!this.selected||(!this.renderer.isConnector(this.selected)&&(!this.selected.getElementsByTagName("text-bound")>0)))return;
- var text=$('__shapeText');
- if(!text.style.visibility=="visible")return;
- var bounds=this.renderer.getTextBounds(this.selected,text.value,this.zoom);
- text.style.marginLeft=bounds.x>3?(bounds.x-3):0;
- text.style.marginTop=bounds.y>3?(bounds.y-3):0;
- if(bounds.width>=35){
- text.style.width=parseInt(bounds.width)+6;
- }
- else{
- text.style.width=35;
- }
- if(bounds.height>=35){
- text.style.height=parseInt(bounds.height)+6;
- }
- else{
- text.style.height=35;
- }
- setTimeout("c.manageTextSize()",100);
- }
- /**
- *basically set the font of the test area based on either
- *the currently selected shape's font properties or the default
- *if the current shape is empty
- **/
- RichDrawEditor.prototype.setTextAreaFont=function(text){
- var shapeFont=this.renderer.getFont(this.selected);
- if(shapeFont.size!=''){
- text.style.fontSize=(shapeFont.size*this.zoom);
- }
- else{
- text.style.fontSize=(this.font.size*this.zoom);
- }
-
- if(shapeFont.color!=''){
- text.style.strokecolor=shapeFont.color;
- text.style.color=shapeFont.color;
- }
- else{
- text.style.strokecolor=this.font.color;
- text.style.color=this.font.color;
- }
- if(shapeFont.family!=''){
- text.style.fontFamily=shapeFont.family;
-
- }
- else{
- text.style.fontFamily=this.font.family;
- }
- if(shapeFont.bold!=''){
-
- text.style.fontWeight=shapeFont.bold;
- }
- else{
- text.style.fontWeight=this.font.bold;
- }
- if(shapeFont.italics!=''){
- text.style.fontStyle=shapeFont.italics;
- }
- else{
- text.style.fontStyle=this.font.italics;
- }
-
- }
- /**
- *called when user clicks an area other than the active text area,
- *signals end of text editing, time to set the text in the shape
- **/
- RichDrawEditor.prototype.onTextEditEnd=function(event){
- if(!this.selected||!this.textEditMode||!event){
- return;
- }
- else{
-
- var source=Event.element(event);
- if(event&&source&&source.id=="__shapeText"){
- return;
- }
- this.finishTextEdit();
- this.unselect();
- }
-
-
- };
- /**
- *this method should be called when we want to force the text edit operation to end
- **/
- RichDrawEditor.prototype.finishTextEdit=function(){
- setHelp("Finished editing text");
- var shapeText=$('__shapeText');
- var text=shapeText.value;
- if(!text||text.length==0)text=" ";
- this.clearShapeText();
- var shapeFont=this.renderer.getFont(this.selected);
- this.renderer.setShapeText(this.selected,text,this.font,false,shapeFont,this.zoom);
- if(this.mode=="text"&&!this.textToolBeginNew)
- {
- var transmitData = this.copyToRemote();
- if (transmitData != null)
- gApplication.transmit('w', "cpy " + transmitData);
- }
- else
- gApplication.transmit('w', 'cmd txt txt ' + this.selected.id + ' ' + text);
-
- if(!this.renderer.isConnector(this.selected)){
- this.resetTextForAttachedConnectors(this.selected);
- }
- shapeText.style.visibility="hidden";
- this.textEditMode=false;
- Event.observe(this.container, "mousedown", this.onMouseDownListener);
- Event.observe(this.container, "mouseup", this.onMouseUpListener);
- Event.observe(this.container, "selectstart", this.onSelectStartListener);
- Event.observe(this.container,'keypress',this.onKeyPressListener);
- Event.observe(this.container,'keyup',this.onKeyUpListener);
- Event.stopObserving(this.container,"mousedown",this.onTextEditEndListener);
-
- }
-
- /**
- *clear the shape text, this removes the shape text and stores it in a temporary location, we do this for performance
- * reasons, since we don't want to draw every single shape line every time we move.
- * @param shape--optional, if no shape provided, this.selected will be used
- **/
-
- RichDrawEditor.prototype.clearShapeText=function(shape){
- var subject=shape;
- if(!subject){
- subject=this.selected;
- }
- if(subject){
- this.renderer.getShapeText(subject);
- this.renderer.getFont(subject);
- this.renderer.clearShapeText(subject);
- if(!this.renderer.isConnector(subject)){
- this.clearTextForAttachedConnectors(subject);
- }
- }
-
- }
- /**
- *reset the shape text after the shape move is complete
- *@param shape--optional, if no shape provided, this.selected will be used
- */
- RichDrawEditor.prototype.resetShapeText=function(shape){
-
- var subject=shape;
- if(!subject){
- subject=this.selected;
- }
- if(subject){
-
- var text=this.renderer.getShapeText(subject);
- var shapeFont=this.renderer.getFont(subject);
- if(text){
- this.renderer.setShapeText(subject,text,this.font,false,shapeFont,this.zoom);
- }
- if(!this.renderer.isConnector(subject)){
- this.resetTextForAttachedConnectors(subject);
- }
- }
- }
- /**
- * clear the text for all the connectors attached to a particular shape
- * @param shape--optional, if no shape provided, this.selected will be used
- */
- RichDrawEditor.prototype.clearTextForAttachedConnectors=function(shape){
- var subject=shape;
- if(!subject)
- subject=this.selected;
- var connList=this.renderer.getAllConnectorsForShape(subject);
- for(var i=0;i<connList.length;i++){
- if(connList[i]){
- this.clearShapeText(connList[i]);
- }
- }
- }
- /**
- * reset the text for all the connectors attached to a particular shape
- * @param shape--optional, if no shape provided, this.selected will be used
- */
- RichDrawEditor.prototype.resetTextForAttachedConnectors=function(shape){
- var subject=shape;
- if(!subject)
- subject=this.selected;
- var connList=this.renderer.getAllConnectorsForShape(shape);
- for(var i=0;i<connList.length;i++){
- if(connList[i]){
- this.resetShapeText(connList[i]);
- }
- }
- }
- /****************************END TEXT functions************************************/
-
-
- /**
- *getSeletedElement
- **/
- RichDrawEditor.prototype.getSelectedElement = function() {
- return this.selected;
- };
-
- /**
- *set grid
- **/
- RichDrawEditor.prototype.setGrid = function(horizontal, vertical) {
- this.gridX = horizontal;
- this.gridY = vertical;
- };
-
- /**
- *during open, we first reset zoom to 1, add the shapes and then set it back to "zoom-factor"
- *
- **/
- RichDrawEditor.prototype.open=function(div){
-
- this.removeAll();
- //reset the zoom to 1
- this.setZoom((1.0/this.zoom));
- //now call the renderer specific operations for open
- this.renderer.open(div);
- //get all shapes
- var nodes=this.renderer.getAllShapes(this.container.ownerDocument);
- var nodeArray=$A(nodes);
- //get all connectors
- nodes=this.renderer.getAllConnectors(this.container.ownerDocument);
- for(var i=0;i<nodes.length;i++){
- nodeArray[nodeArray.length]=nodes[i];
- }
- for(var i=0;i<nodeArray.length;i++){
- var node=nodeArray[i];
- this.addNewShapeListeners(node);
- }
-
- //first set the pageSize as derived from the file being opened
- var pageSize=div.getElementsByTagName("page-size");
- var width=this.DEFAULT_PAGE_WIDTH;
- var hieght=this.DEFAULT_PAGE_HEIGHT;
- if(pageSize&&pageSize.length>0){
- width=pageSize.item(0).getAttribute("width");
- hieght=pageSize.item(0).getAttribute("height");
-
- }
- this.setPageSize(width,hieght);
- //now set the zoom
- var zoomElement=div.getElementsByTagName("zoom-factor");
- var factor=0.8;
- if(zoomElement&&zoomElement.length>0){
- factor=zoomElement.item(0).getAttribute("factor");
-
- }
- this.setZoom(factor);
- $('_zoomValue').innerHTML=(this.getZoom()*100).toFixed(0)+"%";
- };
-
- /**
- *used by new function to reset the editor to defaults in prepration for new
- */
- RichDrawEditor.prototype.reset=function(){
-
- gApplication.transmit('w', 'cmd reset');
-
- this.removeAll();
- this.setPageSize(this.DEFAULT_PAGE_WIDTH,this.DEFAULT_PAGE_HEIGHT);
- }
-
- /**
- *used by "new" toolbar function, clear the canvas
- **/
- RichDrawEditor.prototype.removeAll=function(){
- this.unselect();
- var nodes=this.renderer.getAllShapes(this.container.ownerDocument);
-
- var nodeArray=$A(nodes);
- nodes=this.renderer.getAllConnectors(this.container.ownerDocument);
- for(var i=0;i<nodes.length;i++){
- nodeArray[nodeArray.length]=nodes[i];
- }
- for(var i=0;i<nodeArray.length;i++){
- var node=nodeArray[i];
- this.renderer.remove(node);
- }
-
- }
- /**
- *set the current edit mode
- **/
- RichDrawEditor.prototype.setMode=function (value){
- this.mode=value;
- if(value=='line'){
- this.renderer.setCursor(this.container,"./cursors/line-draw.cur");
- }
- else if(value=='ortho-line'){
- this.renderer.setCursor(this.container,"./cursors/orth-draw.cur");
- }
- else if(value=='curve-line'){
- this.renderer.setCursor(this.container,"./cursors/curve-draw.cur");
- }
- else if (value=='text'){
- this.renderer.setCursor(this.container,"./cursors/text.cur");
- }
- else{
- this.renderer.setCursor(this.container,"default");
- }
-
- }
- /**
- *this is the driver for all toolbar related commands,
- *if a shape is selected the command is delegated to the renderer
- *otherwise it is handled by the editor itself
- **/
- RichDrawEditor.prototype.editCommand = function(cmd, value)
- {
- this.externaleditCommand(cmd, value, false);
- }
- RichDrawEditor.prototype.externaleditCommand = function(cmd, value, external)
- {
- if (!external && this.initialized)
- {
- if (!this.selected)
- gApplication.transmit('w', 'cmd ' + cmd + " " + value);
- else
- gApplication.transmit('w', 'cmd ' + cmd + " " + value + " " + this.selected.id);
- }
- //debugger;
- if (cmd == 'mode') {
- this.setMode(value);
- }
- if(cmd=='zoom'){
- this.setZoom(value);
- }
- else if (this.selected == null) {
- if (cmd == 'fillcolor') {
- this.fillColor = value;
- }
- else if (cmd == 'linecolor') {
- this.lineColor = value;
- }
- else if (cmd == 'linewidth') {
- this.lineWidth = parseInt(value) + 'px';
- }
- else if (cmd=='opacity'){
- this.opacity=value;
- }
- else if (cmd=='gradient'){
- this.gradient=value;
- }
- else if (cmd=='shadow'){
- this.shadowOn=value;
- }
- else if(cmd=='linestyle'){
- this.lineStyle=value;
- }
- else if(cmd=='fontSize'){
- this.font.size=value;
- }
- else if(cmd=='fontFamily'){
- this.font.family=value;
- }
- else if(cmd=='bold'){
- if(this.font.bold=='bold'){
- this.font.bold='normal';
- }
- else{
- this.font.bold='bold';
- }
- }
- else if(cmd=='italic'){
- if(this.font.italics=='italic'){
- this.font.italics='normal';
- }
- else{
- this.font.italics='italic';
- }
- }
- else if(cmd=='fontColor'){
- this.font.color=value;
- }
- else if(cmd=='align'){
- this.font.align=value;
- }
- }
- else {
-
- this.renderer.editCommand(this.selected, cmd, value,this.zoom);
- if(this.textEditMode==true){
- if(cmd=='fontColor'||cmd=='align'||cmd=='italic'||cmd=='bold'||cmd=='fontFamily'||cmd=='fontSize')
- this.setTextAreaFont($('__shapeText'));
-
- }
- }
- }
-
- /**
- * set the page width and heigh and zoom it according to current zoom factor
- **/
- RichDrawEditor.prototype.setPageSize=function(width,height){
- if(width>this.MAX_WIDTH){
- setHelp("<font color='red'>Maximum width allowed is:"+this.MAX_WIDTH+"</font>");
- }
- else if(height>this.MAX_HEIGHT){
- setHelp("<font color='red'>Maximum height allowed is:"+this.MAX_HEIGHT+"</font>");
-
- }
- else{
- this.width=width;
- this.height=height;
- this.page.style.width=(this.width*this.zoom)+'px';
- this.page.style.height=(this.height*this.zoom)+'px';
- }
- this.updateShapeInfo(null);
-
- }
- /**
- *get the page size and width return as an array with elements "width", "height"
- **/
- RichDrawEditor.prototype.getPageSize=function(){
- var size=new Array();
- size['width']=this.width;
- size['height']=this.height;
- return size;
- }
- /**zoom functions**/
- /**
- *set zoom: first set the zoom for the container, then call setShapeZoom for shapes
- **/
- RichDrawEditor.prototype.setZoom=function(value){
-
- value=(this.zoom*value).toFixed(2);
- if(value<0.15||value>4.0)return;
- this.prevZoom=this.zoom;
- this.zoom=value;
- var width=this.page.style.width.split('px')[0];
- var height=this.page.style.height.split('px')[0];
- width=Math.round(width*(value/this.prevZoom));
- height=Math.round(height*(value/this.prevZoom));
- this.page.style.width=width+'px';
- this.page.style.height=height+'px';
- this.setShapeZoom(this.container,value,this.prevZoom);
- }
- /**
- *set the zoom on all individual shapes, call setLineZoom for lines
- **/
- RichDrawEditor.prototype.setShapeZoom=function(doc,value,prevZoom){
- this.renderer.remove($('tracker-group'));
- this.renderer.remove($('active-shape-tracker'));
- var nodes=this.renderer.getAllShapes(doc);
- var length=nodes.length;
- for(var i=0;i<nodes.length;i++){
-
- var shape=nodes[i];
- var rect=this.renderer.bounds(shape);
-
- this.renderer.setWidth(shape,Math.round(parseFloat(rect['width'])*(value/prevZoom)));
- this.renderer.setHeight(shape,Math.round(parseFloat(rect['height'])*(value/prevZoom)));
-
- this.renderer.setY(shape,Math.round(parseFloat(rect['y'])*(value/prevZoom)));
- this.renderer.setX(shape,Math.round(parseFloat(rect['x'])*(value/prevZoom)));
- this.renderer.updateRotation(shape);
- var text=this.renderer.getShapeText(shape,doc);
- var font=this.renderer.getFont(shape);
- this.renderer.clearShapeText(shape);
- if(text)
- this.renderer.setShapeText(shape,text,this.font,false,font,value);
-
- }
-
- this.setLineZoom(doc,value,prevZoom);
- this.renderer.updateTracker(this.selected);
- }
-
- /**
- *now set the zoom on all lines
- **/
- RichDrawEditor.prototype.setLineZoom=function(doc,value,prevZoom){
- var nodes=this.renderer.getAllConnectors(doc);
- var length=nodes.length;
- for(var i=0;i<nodes.length;i++){
- var shape=nodes[i];
- var fromX=this.renderer.getConnectorFromX(shape) * (value/prevZoom);
- var fromY=this.renderer.getConnectorFromY(shape) * (value/prevZoom);
- var toX=this.renderer.getConnectorToX(shape) *(value/prevZoom);
- var toY=this.renderer.getConnectorToY(shape)*(value/prevZoom);
- this.renderer.moveLinePoint(shape,fromX,fromY,true);
- this.renderer.moveLinePoint(shape,toX,toY,false);
- //now get the control points if any
- if(this.renderer.getConnectorType(shape)=='curve-line'){
- var control1=this.renderer.getControl1(shape);
- var cx1=control1.x* (value/prevZoom);
- var cy1=control1.y*(value/prevZoom);
- this.renderer.setControl1(shape,cx1,cy1);
- var control2=this.renderer.getControl2(shape);
- var cx2=control2.x* (value/prevZoom);
- var cy2=control2.y*(value/prevZoom);
- this.renderer.setControl2(shape,cx2,cy2);
- }
-
- var text=this.renderer.getShapeText(shape,doc);
- var font=this.renderer.getFont(shape);
- this.renderer.clearShapeText(shape);
- if(text)
- this.renderer.setShapeText(shape,text,this.font,false,font,value,doc);
-
- }
- }
- /**
- *get zoom factor
- **/
- RichDrawEditor.prototype.getZoom=function(){
- return this.zoom;
- }
-
- /**
- *return the current value for various commands e.g current fill value, opacity etc. If the shape is selected, the command is delegated
- *to the renderer, otherwise handled by the editor
- **/
- RichDrawEditor.prototype.queryCommand = function(cmd)
- {
- if (cmd == 'mode') {
- return this.mode;
- }
- else if (this.selected == null) {
- if (cmd == 'fillcolor') {
- return this.fillColor;
- }
- else if (cmd == 'linecolor') {
- return this.lineColor;
- }
- else if (cmd == 'linewidth') {
- return this.lineWidth;
- }
- else if(cmd=='opacity'){
- return this.opacity;
- }
- else if(cmd=='gradient'){
- return this.gradient;
- }
- else if(cmd=='shadow'){
- return this.shadowOn;
- }
- else if(cmd=='fontSize'){
- return this.font.size;
- }
- else if(cmd=='fontFamily'){
- return this.font.family;
- }
- else if(cmd=='bold'){
- return this.font.bold;
- }
- else if(cmd=='italics'){
- return this.font.italics;
- }
- else if(cmd=='fontColor'){
- return this.font.color;
- }
- else if(cmd=='align'){
- return this.font.align;
- }
- else if(cmd=='font'){
- return this.font;
- }
- else if(cmd=='linedashstyle'){
- return this.linedashstyle;
- }
- else if(cmd=='linestyle'){
- return this.lineStyle;
- }
- }
- else {
- return this.renderer.queryCommand(this.selected, cmd);
- }
- }
-
-
- RichDrawEditor.prototype.onSelectStart = function(event) {
- return false;
- }
- /**
- * for efficieny purposes we do not redraw the text everytime a shape is moved,
- *which means that when the move related keys are released,
- * we need to reset shape text
- **/
- RichDrawEditor.prototype.onKeyUp=function(event){
-
- var code=event.keyCode;
- if((code==46||code==37||code==38||code==39||code==40)&&this.textEditMode==true)
- return true;
- if(code==37||code==38||code==39||code==40||code==82||code==76){
- this.clearShapeText();
- this.resetShapeText();
- }
- }
-
- /**
- *handle various key events
- **/
-
- RichDrawEditor.prototype.onKeyPress=function(event){
- var code=event.keyCode;
- var stop=false;
- var unicode=event.charCode?event.charCode:event.keyCode;
- var actualKey=String.fromCharCode(unicode);
- actualKey=actualKey.toLowerCase();
- if((code==46||code==37||code==38||code==39||code==40)&&this.textEditMode==true)
- return;
- if (gTextEditMode)
- return;
-
- if(46==code&&!this.textEditMode){
- if (this.selected)
- gApplication.transmit('w', 'cmd deleteSelection ' + this.selected.id);
- this.deleteSelection();
- stop=true;
- }
- //disable fine moves as this will probably generate a lot of traffic for large workspaces.
- /*else if(37==code&&!this.textEditMode){
- this.clearShapeText();
- this.fineMove(1,0,0,0);
- stop=true;
- }
- else if(38==code&&!this.textEditMode){
- this.clearShapeText();
- this.fineMove(0,0,1,0);
- stop=true;
- }
- else if(39==code&&!this.textEditMode){
- this.clearShapeText();
- this.fineMove(0,1,0,0);
- stop=true;
- }
- else if(40==code&&!this.textEditMode){
- this.clearShapeText();
- this.fineMove(0,0,0,1);
- stop=true;
- }
- else if('r'==actualKey){
- if(event.shiftKey&&!this.textEditMode){
- this.clearShapeText();
- this.fineRotateSelection(1);
- stop=true;
- }
- }
- else if('l'==actualKey){
- if(event.shiftKey&&!this.textEditMode){
- this.clearShapeText();
- this.fineRotateSelection(-1);
- stop=true;
- }
- }*/
- else if('x'==actualKey){
- if(event.ctrlKey&&!this.textEditMode)
- { this.cut();
- if (this.selected)
- gApplication.transmit('w', 'cmd deleteSelection ' + this.selected.id);
-
- }
- stop=true;
- }
- else if('c'==actualKey){
- if(event.ctrlKey&&!this.textEditMode)
- this.copy();
- stop=true;
- }
- else if('v'==actualKey){
- if(event.ctrlKey&&!this.textEditMode)
- this.paste();;
- stop=true;
- }
- else if('b'==actualKey){
- if(event.ctrlKey){
- this.editCommand("bold");
- stop=true;
- }
- }
- else if('i'==actualKey){
- if(event.ctrlKey){
- this.editCommand("italic");
- stop=true;
-
- }
- }
- else{
- stop=false;
- }
-
- if(stop&&!this.textEditMode){
- Event.stop(event);
- return false;
- }
- else{
- return true;
- }
- }
-
- /*******************MOUSE OVER***************************/
- /**
- *if the mouse is over the tracker set the appropriate cursor.
- *This method needs some serious cleaning up,
- *there is nothing wrong with it except that the logic could be performed much more elegantly.
- **/
- RichDrawEditor.prototype.onMouseOver=function(event){
-
- var source=Event.element(event);
- if(source.id=='resize-bottom'||source.id=='resize-right'||source.id=="tracker-rotate"||
- source.id=='resize-left'||source.id=='resize-top'){
- var offset = Position.cumulativeOffset(this.container);
- var snappedX = (Event.pointerX(event) - offset[0]) / this.gridX * this.gridX;
- var snappedY = (Event.pointerY(event) - offset[1]) / this.gridY * this.gridY;
-
- var rotation=this.renderer.bounds(this.selected)['rotation'];
- rotation=rotation%360;
- if(source.id=='resize-bottom'){
- source.style.cursor='s-resize';
- if(rotation!=null&&((rotation>=45&&rotation<=135)||(rotation>=225&&rotation<=315))){
- source.style.cursor='e-resize';
- }
- else{
- source.style.cursor='s-resize';
- }
- }
- else if(source.id=='resize-top'){
- source.style.cursor='s-resize';
- if(rotation!=null&&((rotation>=45&&rotation<=135)||(rotation>=225&&rotation<=315))){
- source.style.cursor='e-resize';
- }
- else{
- source.style.cursor='s-resize';
- }
- }
- else if(source.id=='resize-right'){
- source.style.cursor='e-resize';
- if(rotation!=null&&((rotation>=45&&rotation<=135)||(rotation>=225&&rotation<=315))){
- source.style.cursor='s-resize';
- }
- else{
- source.style.cursor='e-resize';
- }
- }
- else if(source.id=='resize-left'){
- source.style.cursor='e-resize';
-
- if(rotation!=null&&((rotation>=45&&rotation<=135)||(rotation>=225&&rotation<=315))){
- source.style.cursor='s-resize';
- }
- else{
- source.style.cursor='e-resize';
- }
-
- }
- else if(source.id=="tracker-rotate"){
-
- source.style.cursor='move';
- this.resizeMode="rotate";
- }
-
- }
-
- return false;
- }
-
- /*******************MOUSE DOWN***************************/
- /**
- *handle mouse down related events, another refactoring candidate, too much going on in here...
- **/
- RichDrawEditor.prototype.onMouseDown = function(event) {
-
- var offset = Position.cumulativeOffset(this.container);
- var snappedX = Math.round((Event.pointerX(event) - offset[0]) / this.gridX) * this.gridX;
- var snappedY = Math.round((Event.pointerY(event) - offset[1]) / this.gridY) * this.gridY;
- var source=Event.element(event);
- if(source.id=='resize-bottom'||source.id=='resize-right'||source.id=="tracker-rotate"||
- source.id=='resize-left'||source.id=='resize-top'||source.id=='resize-from'||source.id=='resize-to'
- ||source.id=='control1'||source.id=='control2'){
- this.prevMode=this.mode;
- this.setMode('resize');
- if(this.selected){
- this.mouseDownX = snappedX;
- this.mouseDownY = snappedY;
- var rect=this.renderer.bounds(this.selected);
- this.prevWidth=rect['width'];
- this.prevLeft=rect['x'];
- this.prevHeight=rect['height'];
- this.prevTop=rect['y'];
- this.prevRotation=rect['rotation'];
- if(!this.prevRotation)
- this.prevRotation=0;
-
- if(source&&source.id){
- if(source.id=='resize-from'){
- this.resizeMode='line-from';
- }
- else if(source.id=='resize-to'){
- this.resizeMode='line-to';
- }
- else if(source.id=='control1'){
- this.resizeMode='control1';
-
- }
- else if(source.id=='control2'){
- this.resizeMode='control2';
-
- }
- else if(source.id=='resize-bottom'){
- this.resizeMode="bottom-stretch";
-
- }
- else if(source.id=='resize-top'){
- this.resizeMode="top-stretch";
-
- }
- else if(source.id=='resize-right'){
- this.resizeMode="right-stretch";
-
- }
-
- else if(source.id=='resize-left'){
- this.resizeMode="left-stretch";
-
- }
- else if(source.id=="tracker-rotate"){
- this.resizeMode="rotate";
-
- }
- this.clearShapeText();
- }
-
- }
-
-
- // if(this.resizeMode=="rotate"){
- // setHelp("For Fine rotation use <B>Shift+R</B> and <B>Shift+L</B>");
- // }
- Event.observe(this.container, "mousemove", this.onDrawListener);
- }
- else if (this.mode != 'select'&&this.mode!='resize') {
-
- this.unselect();
- setHelp("Drag your mouse to size the selected shape");
- this.mouseDownX = snappedX;
- this.mouseDownY = snappedY;
- if(this.mode!='line'&&this.mode!='ortho-line'&&this.mode!='curve-line'){
- var mouseX=(this.mouseDownX*1)+this.container.parentNode.scrollLeft;
- var mouseY=( this.mouseDownY*1)+this.container.parentNode.scrollTop;
-
- this.selected = this.renderer.create(this.mode, this.fillColor, this.lineColor, this.lineWidth, mouseX, mouseY, 1, 1,this.opacity,this.gradient,this.shadowOn);
- this.selected.setAttribute('id', 'shape:' + createUUID());
- this.addNewShapeListeners(this.selected);
- if(this.mode=="text"){
- this.textToolBeginNew=true;
- }
- }
-
- else{
- var mouseX=(this.mouseDownX*1)+this.container.parentNode.scrollLeft;
- var mouseY=( this.mouseDownY*1)+this.container.parentNode.scrollTop;
- this.unselect();
- this.selected = this.renderer.createLine(this.mode, this.lineColor, this.lineWidth, mouseX, mouseY,this.lineStyle);
- this.selected.setAttribute('id', 'connector:' + createUUID());
- this.addNewShapeListeners(this.selected);
-
- }
- Event.observe(this.container, "mousemove", this.onDrawListener);
- this.renderer.setCursor(this.container,'crosshair');
- }
- else {
- if (this.mouseDownX != snappedX || this.mouseDownY != snappedY)
- this.unselect();
- }
-
- return false;
- };
- RichDrawEditor.prototype.isLineDrawMode=function(){
- return (this.mode=='line'||this.resizeMode=='line-from'||this.resizeMode=='line-to'||this.mode=='ortho-line'
- ||this.mode=='curve-line')
- }
- /**
- *if the mode is line draw then show connection points
- **/
- RichDrawEditor.prototype.onShapeMouseEnter=function(event){
- var source=Event.element(event);
- var shape=this.renderer.getShapeFromEventSource(source);
- //setHelp(shape.id);
- if(!this.renderer.isConnector(shape)){
- var newActiveShape=shape;
- if((this.lineActiveShape&&newActiveShape&&this.lineActiveShape.id==newActiveShape.id)&&newActiveShape.id)
- //revisit this
- // ||(newActiveShape.id&&newActiveShape.id.indexof("shape")<0))
- return;
- else{
-
-
- if(this.isLineDrawMode()){
- this.renderer.remove($("active-shape-tracker"));
- this.lineActiveShape=newActiveShape;
-
- this.renderer.showConnectionPoints(this.lineActiveShape);
- }
- }
- }
- if(!this.isLineDrawMode()&&this.mode!='text'){
-
- this.renderer.setCursor(this.container,"move");
-
- }
- };
-
- /*******************MOUSE OUT***************************/
-
- RichDrawEditor.prototype.onShapeMouseOut=function(event){
- if(!this.isLineDrawMode()&&this.mode!="text")
- this.renderer.setCursor(this.container,"default");
- }
-
- /**
- *if the mouse leaves the container, stop listening to some events
- **/
- RichDrawEditor.prototype.onMouseOut=function(event){
-
- if(event.toElement&&(event.toElement.id=='_body'||event.toElement.id=='_surround'||event.toElement.id=="palette")){
-
- if((this.mode!='resize'&&this.mode!='select'&&this.mode!="text"))
- {
- var transmitData = this.copyToRemote();
- if (transmitData != null)
- gApplication.transmit('w', "cpy " + transmitData);
- }
- else if (this.selected)
- {
- var rect=new Object();
- rect=this.renderer.bounds(this.selected);
- if(!this.renderer.isConnector(this.selected))
- {
- //a shape
- rect['x']=(rect['x']*(1.0/this.zoom)).toFixed(0);
- rect['y']=(rect['y']*(1.0/this.zoom)).toFixed(0);
- rect['width']=(rect['width']*(1.0/this.zoom)).toFixed(0);
- rect['height']=(rect['height']*(1.0/this.zoom)).toFixed(0);
- var transmitData = "mvs " + this.selected.id + " " + rect['width'] + " " + rect['height'] + " " + rect['x'] + " " + rect['y'] + " " + rect['rotation'];
-
- }
- else{
- //a connector
- rect['x']=(rect['x']*(1.0/this.zoom)).toFixed(0);
- rect['y']=(rect['y']*(1.0/this.zoom)).toFixed(0);
- rect['x2']=(rect['x2']*(1.0/this.zoom)).toFixed(0);
- rect['y2']=(rect['y2']*(1.0/this.zoom)).toFixed(0);
- var transmitData = "mvc " + this.selected.id + " " + rect['x'] + " " + rect['x2'] + " " + rect['y'] + " " + rect['y2'] + " " + rect['type'];
- }
- gApplication.transmit('w', transmitData);
- }
-
-
-
- Event.stopObserving(this.container, "mousemove", this.onDrawListener);
- Event.stopObserving(this.container, "mousemove", this.onDragListener);
- }
- }
-
- /**
- *respond to various mouse up events
- */
- RichDrawEditor.prototype.onMouseUp = function(event)
- {
-
- if (this.mode != 'select'&&this.mode!='resize'&&this.mode!='line'&&this.mode!='ortho-line')
- {
- setHelp("Click on the shape to select it");
- }
-
- if((this.mode!='resize'&&this.mode!='select'&&this.mode!="text"))
- {
- var transmitData = this.copyToRemote();
- if (transmitData != null)
- gApplication.transmit('w', "cpy " + transmitData);
- }
- else if (this.selected)
- {
- var rect=new Object();
- rect=this.renderer.bounds(this.selected);
- if(!this.renderer.isConnector(this.selected))
- {
- //a shape
- rect['x']=(rect['x']*(1.0/this.zoom)).toFixed(0);
- rect['y']=(rect['y']*(1.0/this.zoom)).toFixed(0);
- rect['width']=(rect['width']*(1.0/this.zoom)).toFixed(0);
- rect['height']=(rect['height']*(1.0/this.zoom)).toFixed(0);
- var transmitData = "mvs " + this.selected.id + " " + rect['width'] + " " + rect['height'] + " " + rect['x'] + " " + rect['y'] + " " + rect['rotation'];
-
- }
- else{
- //a connector
- rect['x']=(rect['x']*(1.0/this.zoom)).toFixed(0);
- rect['y']=(rect['y']*(1.0/this.zoom)).toFixed(0);
- rect['x2']=(rect['x2']*(1.0/this.zoom)).toFixed(0);
- rect['y2']=(rect['y2']*(1.0/this.zoom)).toFixed(0);
- var transmitData = "mvc " + this.selected.id + " " + rect['x'] + " " + rect['x2'] + " " + rect['y'] + " " + rect['y2'] + " " + rect['type'];
- }
- gApplication.transmit('w', transmitData);
- }
-
- Event.stopObserving(this.container, "mousemove", this.onDrawListener);
- Event.stopObserving(this.container, "mousemove", this.onDragListener);
-
- if(this.dragStarted)
- {
- this.clearShapeText();
- this.resetShapeText();
- this.dragStarted=false;
- }
-
- if(this.mode=='line'||this.mode=='curve-line'||this.resizeMode=='line-from'||this.resizeMode=='line-to'||this.mode=='ortho-line')
- {
- //todo add show marker logic here
- if(this.resizeMode=='line-from')
- this.renderer.connectLine(this.lineActiveShape,this.selected,"from");
- else if(this.resizeMode=='line-to'||this.mode=='line'||this.mode=='ortho-line'||this.mode=='curve-line')
- this.renderer.connectLine(this.lineActiveShape,this.selected,"to");
-
- this.renderer.remove($('active-shape-tracker'));
- this.lineActiveShape=null;
- this.clearShapeText();
- this.resetShapeText();
- }
- if(this.mode=="text"&&this.textToolBeginNew){
- this.beginTextToolEdit(this.selected);
- this.textToolBeginNew=false;
- }
- else if(this.mode=="text"&&!this.textToolBeginNew){
- setHelp("<font color='red'>Text Mode:</font>Click again to draw another text shape");
-
- var transmitData = this.copyToRemote();
- if (transmitData != null)
- gApplication.transmit('w', "cpy " + transmitData);
-
- }
- if(this.mode=='resize'){
- Event.stopObserving(this.container, "mousemove", this.onDrawListener);
- this.clearShapeText();
- this.resetShapeText();
- this.setMode(this.prevMode);
- this.resizeMode="";
- }
-
- if (this.mode != 'select'&&this.mode!='line'&&this.mode!='ortho-line'&&this.mode!="text"&&this.mode!='curve-line') {
- this.setMode('select');
- }
- else{
- //mainly to refresh the cursor!!!
- this.setMode(this.mode);
- }
-
-
- };
- /**
- *begin text tool edit will first set the stroke-width to 0 and then start text editing
- *@param {shape} selected shape
- **/
- RichDrawEditor.prototype.beginTextToolEdit=function(shape){
- this.renderer.setStrokeWidth(shape,"0px");
- this.renderer.setOpacity(shape,"0.0");
- this.startTextEdit(shape);
- }
- /*****************ON DRAG**********************/
- /**
- *move the shape
- **/
- RichDrawEditor.prototype.onDrag = function(event) {
- var offset = Position.cumulativeOffset(this.container);
- var snappedX = Math.round((Event.pointerX(event) - offset[0]) / this.gridX) * this.gridX;
- var snappedY = Math.round((Event.pointerY(event) - offset[1]) / this.gridY) * this.gridY;
-
- var deltaX = snappedX - this.mouseDownX;
- var deltaY = snappedY - this.mouseDownY;
- if(!this.dragStarted==true){
- this.clearShapeText();
- this.dragStarted=true;
- }
- if(this.renderer.isConnector(this.selected)){
- this.renderer.disconnectLineFromShape(this.selected,"to");
- this.renderer.disconnectLineFromShape(this.selected,"from");
- this.renderer.moveCompleteLine(this.selected,this.selectedBounds,deltaX,deltaY);
- this.clearShapeText();
- }
- else{
-
- this.renderer.move(this.selected, (this.selectedBounds.x*1) + deltaX, (this.selectedBounds.y*1) + deltaY);
- this.renderer.moveLineWithShape(this.selected);
- }
- // Update selection tracker
- this.renderer.updateTracker(this.selected);
- this.updateShapeInfo(this.selected);
- };
-
- /**
- *move 1px at a time--reacting to arrow key press
- **/
- RichDrawEditor.prototype.fineMove=function(left,right,up,down){
- if(this.selected){
- if(this.renderer.isConnector(this.selected)) return;
- var deltaX=right-left;
- var deltaY=down-up;
- //this.selectedBounds = this.renderer.bounds(this.selected);
- if(deltaY==0){
- this.renderer.fineMove(this.selected, deltaX, true);
- }
- else{
- this.renderer.fineMove(this.selected, deltaY, false);
- }
-
- this.renderer.moveLineWithShape(this.selected);
- this.renderer.updateTracker(this.selected);
- //this.updateShapeInfo(this.selected);
- this.selectedBounds = this.renderer.bounds(this.selected);
- }
- else{
- setHelp("Select a shape for Fine move");
- }
-
- }
-
- /**************ON DRAW*****************/
- /**
- *either create new or resize existing
- **/
- RichDrawEditor.prototype.onDraw = function(event) {
- if (this.selected == null)
- return;
-
-
- var offset = Position.cumulativeOffset(this.container);
- var snappedX = Math.round((Event.pointerX(event) - offset[0]) / this.gridX) * this.gridX;
- var snappedY = Math.round((Event.pointerY(event) - offset[1]) / this.gridY) * this.gridY;
-
-
- //this means we are drawing a new shape or line on the canvas
-
- if(this.mode!='resize'&&this.mode!='select'){
- var mouseX=(this.mouseDownX*1)+this.container.parentNode.scrollLeft;
- var mouseY=( this.mouseDownY*1)+this.container.parentNode.scrollTop;
- var sx=(snappedX*1)+this.container.parentNode.scrollLeft;
- var sy=(snappedY*1)+this.container.parentNode.scrollTop;
- this.renderer.resize(this.selected, mouseX,mouseY,sx,sy);
- this.updateShapeInfo(this.selected);
- //we show tracker during draw only for connectors
- if(this.renderer.isConnector(this.selected)){
- this.renderer.updateTracker(this.selected);
-
- }
- return;
- }
-
- //otherwise check the resize mode, if the mode is horizontal then keep left static
- //otherwise if mode is vertical keep the top static
-
- if(this.mode=='resize'||this.mode=='select'){
- this.resizeCounter++;
- if(this.resizeCounter!=2){
- return;
- }
- this.resizeCounter=0;
-
- if(this.resizeMode=="line-from"){
-
- var sx=(snappedX*1)+this.container.parentNode.scrollLeft;
- var sy=(snappedY*1)+this.container.parentNode.scrollTop;
- this.renderer.disconnectLineFromShape(this.selected,"from");
- this.renderer.moveLine(this.selected,sx,sy,true);
-
-
- }
- else if(this.resizeMode=="line-to"){
- var sx=(snappedX*1)+this.container.parentNode.scrollLeft;
- var sy=(snappedY*1)+this.container.parentNode.scrollTop;
-
- this.renderer.disconnectLineFromShape(this.selected,"to");
- this.renderer.moveLine(this.selected,sx,sy,false);
-
-
- }
- //add control point listeners
- else if(this.resizeMode=="control1"){
- var sx=(snappedX*1)+this.container.parentNode.scrollLeft;
- var sy=(snappedY*1)+this.container.parentNode.scrollTop;
- this.renderer.setControl1(this.selected,sx,sy);
-
-
- }
- else if(this.resizeMode=="control2"){
- var sx=(snappedX*1)+this.container.parentNode.scrollLeft;
- var sy=(snappedY*1)+this.container.parentNode.scrollTop;
- this.renderer.setControl2(this.selected,sx,sy);
-
-
- }
- //use this for right pull
- if(this.resizeMode=="right-stretch"){
- this.renderer.resizeWidth(this.selected, snappedX,snappedY, this.mouseDownX,this.mouseDownY,this.prevWidth,true);
- this.renderer.moveLineWithShape(this.selected);
- }
- else
- if(this.resizeMode=="left-stretch"){
-
- this.renderer.resizeWidth(this.selected, snappedX,snappedY, this.mouseDownX,this.mouseDownY,this.prevWidth,false);
- this.renderer.moveLineWithShape(this.selected);
- }
- //use this for bottom pull
- else if(this.resizeMode=="bottom-stretch"){
- this.renderer.resizeHeight(this.selected, snappedX,snappedY, this.mouseDownX,this.mouseDownY,this.prevHeight,true);
- this.renderer.moveLineWithShape(this.selected);
- }
- else if(this.resizeMode=="top-stretch"){
- this.renderer.resizeHeight(this.selected, snappedX,snappedY, this.mouseDownX,this.mouseDownY,this.prevHeight,false);
- this.renderer.moveLineWithShape(this.selected);
- }
- else if(this.resizeMode=="rotate"){
- var mouseX=(this.mouseDownX*1)+this.container.parentNode.scrollLeft;
- var mouseY=( this.mouseDownY*1)+this.container.parentNode.scrollTop;
- var sx=(snappedX*1)+this.container.parentNode.scrollLeft;
- var sy=(snappedY*1)+this.container.parentNode.scrollTop;
- this.processRotate(this.selected, sx,sy,mouseX,mouseY);
- this.renderer.moveLineWithShape(this.selected);
- }
- this.renderer.updateTracker(this.selected);
- this.updateShapeInfo(this.selected);
-
- }
- return false;
- };
- /*******************ROTATION FUNCTIONS**********************/
- /**
- *rotate 1 degree at a time
- **/
- RichDrawEditor.prototype.fineRotateSelection=function(angle){
- if(this.selected==null){
- setHelp("Please select a shape to rotate");
- return false;
- }
- //this.selectedBounds = this.renderer.bounds(this.selected);
- this.renderer.fineRotateSelection(this.selected,angle);
- this.renderer.moveLineWithShape(this.selected);
- this.renderer.updateTracker(this.selected);
-
- this.selectedBounds = this.renderer.bounds(this.selected);
- }
-
- /**
- * this method obtains the actual number of degrees to rotate by, renderer performs the actual rotation
- *@param snappedX (currentX)
- *@param snappedY (currentY)
- *@param mouseDownX
- *@param mouseDownY
- **/
- RichDrawEditor.prototype.processRotate=function(shape,snappedX,snappedY,mouseDownX,mouseDownY){
- var rect=this.renderer.bounds(shape);
- var centerX=(rect['x']*1)+(rect['width']/2);
- var centerY=(rect['y']*1)+(rect['height']/2);
- //first translate snapped x and y to origin
- var transX=snappedX-centerX;
- var transY=snappedY-centerY;
- //now we are at origin, our arbitrary point would be 0,-10
- //now take the dot product
- var adotb=(transX*0)+(transY*(-10));
- //now cros product |A|*|B|=sqrt((x1square+y1square))*sqrt((x2square+y2square));
- //we know sqrt((x1square+y1square))=10
- var acrossb=(10)*Math.sqrt((transX*transX)+(transY*transY));
- var theta=adotb/acrossb;
- theta=Math.acos(theta);
- theta=rad2Deg(theta)
- //if in quadrant 3 or 4
- if(transX<=0)theta=360-theta;
-
- this.renderer.rotate(this.selected,Math.round(theta));
-
-
- }
- /******************* END ROTATION FUNCTIONS**********************/
-
- /**
- *basically when a shape is has a mouse hit...select it. If we are in text edit mode,
- *do nothing, just return;
- *@param the event
- **/
- RichDrawEditor.prototype.onHit = function(event) {
- if(this.textEditMode){
- return;
- }
-
- if (this.mode == 'select') {
- this.unselect();
- var source=Event.element(event);
- this.select(this.renderer.getShapeFromEventSource(source));
- this.selectedBounds = this.renderer.bounds(this.selected);
- var offset = Position.cumulativeOffset(this.container);
- this.mouseDownX = Math.round((Event.pointerX(event) - offset[0]) / this.gridX) * this.gridX;
- this.mouseDownY = Math.round((Event.pointerY(event) - offset[1]) / this.gridY) * this.gridY;
- Event.observe(this.container, "mousemove", this.onDragListener);
- }
- };
- /**
- * update the properties box with shape or page info
- * @param the shape
- **/
- RichDrawEditor.prototype.updateShapeInfo=function(selected){
- var rect=new Object();
- if(selected==null){
- //show page properties
- rect['width'] = this.width;
- rect['height'] = this.height;
- this.pageProps.width.value=rect['width'];
- this.pageProps.height.value=rect['height'];
-
- this.shapeProps.table.style.visibility="hidden";
- this.shapeProps.table.style.display="none";
- this.pageProps.table.style.visibility="visible";
- this.pageProps.table.style.display="";
- this.lineProps.table.style.visibility="hidden";
- this.lineProps.table.style.display="none";
- }
- else{
-
- rect=this.renderer.bounds(selected);
- //this is a shape
- if(!this.renderer.isConnector(selected)){
- rect['x']=(rect['x']*(1.0/this.zoom)).toFixed(0);
- rect['y']=(rect['y']*(1.0/this.zoom)).toFixed(0);
- rect['width']=(rect['width']*(1.0/this.zoom)).toFixed(0);
- rect['height']=(rect['height']*(1.0/this.zoom)).toFixed(0);
- this.shapeProps.width.value=rect['width'];
- this.shapeProps.height.value=rect['height'];
- this.shapeProps.x.value=rect['x'];
- this.shapeProps.y.value=rect['y'];
- this.shapeProps.rotation.value=rect['rotation'];
- this.shapeProps.table.style.visibility="visible";
- this.shapeProps.table.style.display="";
- this.lineProps.table.style.visibility="hidden";
- this.lineProps.table.style.display="none";
- this.pageProps.table.style.visibility="hidden";
- this.pageProps.table.style.display="none";
- }
- else{
- //its a connector
- rect['x']=(rect['x']*(1.0/this.zoom)).toFixed(0);
- rect['y']=(rect['y']*(1.0/this.zoom)).toFixed(0);
- rect['x2']=(rect['x2']*(1.0/this.zoom)).toFixed(0);
- rect['y2']=(rect['y2']*(1.0/this.zoom)).toFixed(0);
- this.lineProps.x1.innerHTML=rect['x'];
- this.lineProps.x2.innerHTML=rect['x2'];
- this.lineProps.y1.innerHTML=rect['y'];
- this.lineProps.y2.innerHTML=rect['y2'];
- this.lineProps.type.innerHTML=rect['type'];
- this.shapeProps.table.style.visibility="hidden";
- this.shapeProps.table.style.display="none";
- this.lineProps.table.style.visibility="visible";
- this.lineProps.table.style.display="";
- this.pageProps.table.style.visibility="hidden";
- this.pageProps.table.style.display="none";
-
- }
- }
-
- };
- /**
- * append a cumulate draw specific page attribute to the save data
- **/
- RichDrawEditor.prototype.appendPageAttribute=function(div,attribute){
- this.renderer.appendPageAttribute(div,attribute);
- }
- /**
- *get the vml/svg data embedded in the richdraw editor
- **/
- RichDrawEditor.prototype.getRealData=function(){
- return this.renderer.getRealData();
- }
- /**
- *take the response text and return valid data from it
- **/
- RichDrawEditor.prototype.getValidDocumentFromResponse=function(response){
- return this.renderer.getValidDocumentFromResponse(response);
-
- }
- /**
- *load palette, does this really belong in the editor?
- **/
- RichDrawEditor.prototype.loadPalette=function(id){
-
- var object=this.renderer.loadXML("shapes/palettes/"+id+".xml");
-
- return object.getElementsByTagName("palette")[0];
-
- }
- /**
- *method to update the shape properties, take zoom factor into account here and also
- *move any connectors attached to the shape
- **/
- RichDrawEditor.prototype.updateShape=function(width,height,x,y,rotation){
-
- if(this.selected){
- var rect=this.selected;
- width=(width*(this.zoom/1.0)).toFixed(0);
- height=(height*(this.zoom/1.0)).toFixed(0);
- x=(x*(this.zoom/1.0)).toFixed(0);
- y=(y*(this.zoom/1.0)).toFixed(0);
- this.renderer.setWidth(this.selected,width);
- this.renderer.setHeight(this.selected,height);
- this.renderer.setX(this.selected,x);
- this.renderer.setY(this.selected,y);
- this.renderer.setRotation(this.selected,rotation);
- this.renderer.updateTracker(this.selected);
- this.renderer.moveLineWithShape(this.selected);
- this.clearShapeText(this.selected);
- this.resetShapeText(this.selected);
-
- } else{
- setHelp("Please select a shape to update");
- }
- }
-
- /**
- *utility function to convert rad to degrees
- **/
-
- function rad2Deg(angle){
- return angle * (180 / Math.PI);
- }
-
- /**
- *create a unique id for shapes
- **/
- function createUUID()
- {
- return [4, 2, 2, 2, 6].map(function(length) {
- var uuidpart = "";
- for (var i=0; i<length; i++) {
- var uuidchar = parseInt((Math.random() * 256)).toString(16);
- if (uuidchar.length == 1)
- uuidchar = "0" + uuidchar;
- uuidpart += uuidchar;
- }
- return uuidpart;
- }).join('-');
- }
-
- function show(object){document.getElementById(object).style.visibility='visible';document.getElementById(object).style.display='';}
-
- function hide(object){document.getElementById(object).style.visibility='hidden';document.getElementById(object).style.display='none';}
-
-
- RichDrawEditor.prototype.setUser=function(aUser){
- this.iUser=aUser;
- }
-
- RichDrawEditor.prototype.handleRemoteCommand=function(param)
- {
- var name = param.substr(0,param.indexOf(" "));
- var remoteData = param.substr(param.indexOf(" ")+1);
-
- var command = remoteData.substring(0,3);
- var content = remoteData.substring(4);
- if (command=="ann")
- {
- //announce start of a drawing
- insertInvitation(name);
- }
- else if (command=="stp")
- {
- //announce end of a drawing
- removeInvitation(name);
- gApplication.removePeer(name);
- }
- else if (command=="con")
- {
- //connect from user
- gApplication.sendPeerList(name);
- sendCurrentState(name);
- gApplication.addPeer(name);
- }
- else if (command=="aus")
- {
- //add user
- gApplication.addPeer(content);
- }
- else if (command=="rus")
- {
- //add user
- gApplication.removePeer(name);
- }
- else if (command=="loa")
- {
- loadData(content);
- }
- else if (command=="cpy")
- {
- var node=this.renderer.paste(content,true);
- //add listener to added child
- this.addNewShapeListeners(node);
- this.clipboard=this.renderer.copy(node);
- return node;
- }
- else if (command=="cmd")
- {
- var temp = content.split(" ");
- var oldID = null;
- if (this.selected)
- oldID=this.selected.id
- if (temp[2])
- this.selected = $(temp[2])
-
- if (temp[0]=="zoom")
- {
- this.externaleditCommand(temp[0], temp[1], true);
- $('_zoomValue').innerHTML=(c.getZoom()*100).toFixed(0)+"%";
- }
- else if (temp[0]=="fontFamily")
- {
- if (temp.length==5)
- {
- this.selected = $(temp[4])
- this.externaleditCommand(temp[0], temp[1] + " " + temp[2] + " " + temp[3], true);
- }
- else if (temp.length==4)
- {
- this.selected = $(temp[3])
- this.externaleditCommand(temp[0], temp[1] + " " + temp[2], true);
- }
- else
- this.externaleditCommand(temp[0], temp[1], true);
- }
- else if (temp[0]=="fillcolor")
- {
- this.externaleditCommand(temp[0], temp[1], true);
- }
- else if (temp[0]=="linecolor")
- {
- this.externaleditCommand(temp[0], temp[1], true);
- }
- else if (temp[0]=="linewidth")
- {
- this.externaleditCommand(temp[0], temp[1], true);
- }
- else if (temp[0]=="linedashstyle")
- {
- this.externaleditCommand(temp[0], temp[1], true);
- }
- else if (temp[0]=="opacity")
- {
- this.externaleditCommand(temp[0], temp[1], true);
- }
- else if (temp[0]=="shadow")
- {
- this.externaleditCommand(temp[0], temp[1], true);
- }
- else if (temp[0]=="gradient")
- {
- this.externaleditCommand(temp[0], temp[1], true);
- }
- else if (temp[0]=="fontSize")
- {
- this.externaleditCommand(temp[0], temp[1], true);
- }
- else if (temp[0]=="fontColor")
- {
- this.externaleditCommand(temp[0], temp[1], true);
- }
- else if (temp[0]=="bold")
- {
- this.externaleditCommand(temp[0], temp[1], true);
- }
- else if (temp[0]=="italic")
- {
- this.externaleditCommand(temp[0], temp[1], true);
- }
- else if (temp[0]=="align")
- {
- this.externaleditCommand(temp[0], temp[1], true);
- }
- else if (temp[0]=="bringtofront")
- {
- this.bringToFront();
- }
- else if (temp[0]=="sendtoback")
- {
- this.sendToBack();
- }
- else if (temp[0]=="reset")
- {
- this.removeAll();
- this.setPageSize(this.DEFAULT_PAGE_WIDTH,this.DEFAULT_PAGE_HEIGHT);
- }
- else if (temp[0]=="deleteSelection")
- {
- this.deleteSelection();
- }
- else if (temp[0]=="txt")
- {
- var newtext = remoteData.substring(9+temp[1].length+temp[2].length);
-
- var shapeFont=this.renderer.getFont(this.selected);
- this.renderer.setShapeText(this.selected,newtext,this.font,false,shapeFont,this.zoom);
- }
- else if (temp[0]=="grid")
- {
- if(temp[0]=='on')
- {
- $('_page').style.backgroundImage="url(images/grid.jpg)";
- }
- else{
- $('_page').style.backgroundImage="";
- }
- }
-
- if (oldID)
- this.select($(oldID));
- }
-
- if (command=="mvs")
- {
- var oldID = null;
- if (this.selected)
- oldID=this.selected.id
- //moving a shape
- var temp = content.split(" ");
- this.selected = $(temp[0]);
- if (this.selected)
- this.updateShape(temp[1], temp[2], temp[3], temp[4], temp[5]);
- if (oldID)
- this.select($(oldID));
- }
- else if (command=="mvc")
- {
- //moving a connector
- }
- else if (command=="pgs")
- {
- //set page size
- var temp = content.split(" ");
- this.setPageSize(temp[0],temp[1]);
- }
- }
-
- function transmit(aUser, aApplication, aMessage)
- {
- //loop through all users and transmit to them
- if (typeof(window.external)!="undefined" && typeof(window.external.transmit)!="undefined")
- window.external.transmit(aUser, aApplication, aMessage);
- }
-
- //Application handling
- function Application()
- {
- this.reset();
- }
-
- Application.prototype.reset=function()
- {
- this.iPeers=new Array();
- this.iSource=false;
- this.iViewing="";
- }
-
- Application.prototype.broadcast=function(application, message)
- {
- if (typeof(window.external)!="undefined" && typeof(window.external.broadcast)!="undefined")
- window.external.broadcast(application, message);
- }
-
- Application.prototype.transmit=function(application, message)
- {
- //loop through all users and transmit to them
- for (var i=0; i < this.iPeers.length; i++)
- {
- if (typeof(window.external)!="undefined" && typeof(window.external.transmit)!="undefined")
- window.external.transmit(this.iPeers[i].iName, application, message);
- }
- }
-
- Application.prototype.sendPeerList=function(aName)
- {
- for (var i=0; i < this.iPeers.length; i++)
- {
- if (typeof(window.external)!="undefined" && typeof(window.external.transmit)!="undefined")
- window.external.transmit(aName, "w", "aus " + this.iPeers[i].iName);
- }
- }
-
- Application.prototype.addPeer=function(aName)
- {
- this.iPeers[this.iPeers.length] = new Peer(aName);
- insertParticipant(aName);
- }
-
- Application.prototype.checkPeerExist=function(aName)
- {
- for (var i = 0; i < this.iPeers.length; i++)
- {
- if (this.iPeers[i].iName == aName)
- return true;
- }
- return false;
- }
-
- Application.prototype.removePeer=function(aName)
- {
- removeParticipant(aName);
- for (var i = 0; i < this.iPeers.length; i++)
- if (this.iPeers[i].iName == aName)
- {
- this.iPeers.splice(i,1);
- return;
- }
- }
-
- function Peer(aName)
- {
- this.iName=aName;
- }
-
- var gApplication;
-
- //announce the drawing to the rest of the workspace.
- function announce()
- {
- if (gApplication.iSource)
- {
- gApplication.broadcast('w', "ann draw");
- if (iConnectionMode!="Private")
- setTimeout('announce()',60000);
- }
- else
- {
- gApplication.broadcast('w', "stp draw");
- }
- }
-
- function initDrawing()
- {
- if (!gApplication.iSource)
- {
- stopDrawing();
- gApplication.iSource = true;
- announce();
- }
- Activate('w');
- hide("startdrawing");
- show("drawparticipant");
- }
-
- function stopDrawing()
- {
- if (gApplication.iSource)
- {
- gApplication.reset();
- announce();
- }
- else
- {
- this.iViewing = "";
- gApplication.transmit('w', "rus ");
- gApplication.reset();
- var invitelist=document.getElementById("Particips");
- invitelist.innerHTML="";
- }
- hide("drawparticipant");
- Activate('c');
- show("startdrawing");
- }
-
- function sendCurrentState(aName)
- {
- /* Try.these(c.renderer.savePolyLinePaths());
- dummy=c.getRealData();
- transmit(aName, 'w', "loa " + dummy);
- */
- var format=c.renderer.EXTENSION;
- var dummy=getAllData(format);
- var data=(dummy.innerHTML)?dummy.innerHTML:dummy.xml;
- transmit(aName, 'w', "loa " + data);
- }
-
- function loadData(content)
- {
- if(content){
- var div=c.getValidDocumentFromResponse(content)
- c.open(div);
- }
- }
-
- function viewDrawing(aName)
- {
- if (aName!=this.iViewing)
- {
- if (this.iViewing)
- {
- //we are viewing somebody, disconnect from them before connecting
- }
- this.iViewing=aName;
-
- if (!gApplication.checkPeerExist(aName))
- {
- gApplication.addPeer(aName);
- gApplication.iSource=false;
- gApplication.transmit('w', "con " + aName);
- }
- hide("startdrawing");
- show("drawparticipant");
- }
- Activate("w");
- }
-
- function insertInvitation(aUser, aMessage)
- {
- var invitelist = document.getElementById("Invites");
- var existingItem = document.getElementById('invite' + aUser);
- if (!existingItem)
- {
- var listElement = document.createElement("li");
- listElement.setAttribute('id', 'invite' + aUser);
- var newlink = document.createElement('a');
- newlink.setAttribute('href', 'javascript:viewDrawing("' + aUser + '")');
- var text = document.createTextNode(aUser);
- newlink.appendChild(text);
- listElement.appendChild(newlink);
- invitelist.appendChild(listElement);
- if (typeof(window.external)!="undefined" && typeof(window.external.observe)!="undefined")
- window.external.observe(aUser);
-
- var chatElement = document.createElement("div");
- var newlink = document.createElement('a');
- newlink.setAttribute('href', 'javascript:viewDrawing("' + aUser + '")');
- var text = document.createTextNode("Click here");
- newlink.appendChild(text);
- var text2 = document.createTextNode(aUser + " started a shared whiteboard. ");
- var text3 = document.createTextNode(" to view or take part in the drawing. ");
- chatElement.appendChild(text2);
- chatElement.appendChild(newlink);
- chatElement.appendChild(text3);
-
- var chat = document.getElementById("c");
- chat.appendChild(chatElement);
- }
- }
-
- function removeInvitation(aUser)
- {
- var invitelist = document.getElementById("Invites");
- var removeItem = document.getElementById('invite' + aUser);
- if (removeItem)
- {
- invitelist.removeChild(removeItem);
- if (typeof(window.external)!="undefined" && typeof(window.external.ignore)!="undefined")
- window.external.ignore(aUser);
- }
- }
-
- function insertParticipant(aUser, aMessage)
- {
- var invitelist = document.getElementById("Particips");
- var existingItem = document.getElementById('participant' + aUser);
- if(!existingItem)
- {
- var listElement = document.createElement("li");
- listElement.setAttribute('id', 'participant' + aUser);
- var text = document.createTextNode(aUser);
- listElement.appendChild(text);
- invitelist.appendChild(listElement);
- if (typeof(window.external)!="undefined" && typeof(window.external.observe)!="undefined")
- window.external.observe(aUser);
- }
- }
-
- function removeParticipant(aUser)
- {
- var invitelist = document.getElementById("Particips");
- var removeItem = document.getElementById('participant' + aUser);
- if (removeItem)
- {
- invitelist.removeChild(removeItem);
- if (typeof(window.external)!="undefined" && typeof(window.external.ignore)!="undefined")
- window.external.ignore(aUser);
- }
- }
-
- function userLeft(aUser)
- {
- gApplication.removePeer(aUser);
- removeInvitation(aUser);
- }
-